﻿@using StackExchange.Opserver.Data.Elastic
@using StackExchange.Opserver.Views.Elastic
@using Roles = StackExchange.Opserver.Models.Roles
@model DashboardModel
@{
    Layout = null;
    var maxTroubleShardsToShow = 250;
    var isAdmin = Current.User.IsInRole(Roles.ElasticAdmin);
}
@helper GetNodeName(string node, Dictionary<string, ElasticCluster.NodeInfoWrap> nodes)
{
    if (node.IsNullOrEmpty())
    {
        <span class="unknown">n/a</span>
        return;
    }
    ElasticCluster.NodeInfoWrap result;
    if (nodes.TryGetValue(node, out result))
    {
        @result.Name
        return;
    }
    <span class="unknown">@node</span>
}
@foreach (var c in Model.Clusters.OrderByWorst(c => c.Status.Data?.MonitorStatus ?? MonitorStatus.Critical))
{
    var shards = (Model.WarningsOnly ? c.TroubledShards : c.ShardStates).ToList();
    if (!shards.Any() || c.Nodes.Data == null)
    {
        continue;
    }
    var nodes = c.Nodes.Data.Nodes.ToDictionary(n => n.GUID);
    var status = shards.Select(s => s.GetMonitorStatus()).GetWorstStatus();
    <table class="cluster-dashboard striped-dashboard">
        <tbody class="node-header" data-name="header-shards-@c.HealthStatus.Data.Name">
            <tr class="category-row">
                <th colspan="9"><h3>@status.IconSpan() @shards.Count.ToComma() Shards @(Model.WarningsOnly ? "in trouble" : "") on @c.HealthStatus.Data.TotalNodeCount.Pluralize("node") (@c.HealthStatus.Data.Name)</h3></th>
            </tr>
            <tr>
                <th></th>
                <th>Index</th>
                <th>State</th>
                <th>Shard #</th>
                <th>Primary</th>
                <th>Node</th>
                <th>Relocating To</th>
                @if (isAdmin)
                {
                    <th>Action</th>
                }
            </tr>
        </tbody>
        <tbody class="node-group" data-name="shards-@c.HealthStatus.Data.Name">
            @foreach (var s in shards.OrderByDescending(s => s.Node.HasValue() || s.RelocatingNode.HasValue())
                .ThenByWorst(s => s.GetMonitorStatus())
                .ThenBy(s => { int j; return int.TryParse(s.Index, out j) ? j : 0; })
                .ThenBy(s => s.Shard)
                .ThenByDescending(s => s.Primary)
                .Take(maxTroubleShardsToShow))
            {
                <tr class="@s.GetMonitorStatus().RowClass()">
                    <td>@s.GetMonitorStatus().IconSpan()</td>
                    <td>@c.GetIndexAliasedName(s.Index)</td>
                    <td>@s.GetPrettyState()</td>
                    <td>@s.Shard</td>
                    <td>@s.Primary</td>
                    <td>@GetNodeName(s.Node, nodes)</td>
                    <td>@GetNodeName(s.RelocatingNode, nodes)</td>
                    @if (isAdmin)
                    {
                        <td>
                            @switch (s.GetPrettyState())
                            {
                                case "Unassigned":
                                    <a href="/elastic/reroute/assign?index=@s.Index.UrlEncode()&shard=@s.Shard" class="background-post">Assign</a>
                                    break;
                                case "Initializing":
                                <a href="/elastic/reroute/cancel?node=@s.Node.UrlEncode()&index=@s.Index.UrlEncode()&shard=@s.Shard" class="background-post">Cancel</a>
                                    break;
                            }
                        </td>
                    }
                </tr>
            }
            @if (shards.Count > maxTroubleShardsToShow)
            {
                <tr><td colspan="@(isAdmin ? 8 : 7)" style="text-align: center">More than @(maxTroubleShardsToShow.ToComma()) in trouble.</td></tr>
            }
        </tbody>
    </table>
    if (c != Model.Clusters.Last())
    {
         <div class="node-dashboard-separator"></div>
    }
}